#include "Anx_uart.h"

/* Private includes ----------------------------------------------------------*/
#include "string.h"
#include "stdio.h"
#include "stdlib.h"
#include "stdarg.h"

/* Private define ------------------------------------------------------------*/
const static char TAG[] = "UART";

#define DEBUG_UART
#ifdef DEBUG_UART
#define Uart_log(fmt, ...) Debug(TAG, fmt, ##__VA_ARGS__)
#else
#define Uart_log(fmt, ...)
#endif
/* Private typedef ------------------------------------------------------------*/


/* Extern variables ---------------------------------------------------------*/
extern DMA_HandleTypeDef hdma_usart1_rx;


/* Private variables ---------------------------------------------------------*/
static char uart_rx_buffer[USART_RX_BUFFER_MAX] = { 0 };
static char uart_tx_buffer[USART_TX_BUFFER_MAX];
static uint16_t uart_rx_index = 0;


#if (SUPPORT_RTOS == 1)
static osMailQDef(uart_rx_mail, 4, char*);
static osMailQId  uart_rx_mail;
static osThreadId uart_rx_handle;
#else
static char uart_rx_flag = 0;    // 接收完成标志
#endif


/* Public variables ---------------------------------------------------------*/


/* Private functions ---------------------------------------------------------*/

__weak void Anx_Rx_Process(char* buf, uint16_t len)
{
    // 该函数用于用户重定义
    Uart_log("len:%d", len);
    Uart_log("%s", buf);

    Anx_UART_SendData(&huart1, "len:%d\r\n", len);
    Anx_UART_SendData(&huart1, "%s\r\n", buf);

    if (Anx_Uart_Strcmp(buf, "runTime"))
    {
        vTaskGetRunTimeStats(uart_tx_buffer);
        Anx_UART_SendData(&huart1, "%s\r\n", uart_tx_buffer);
        Uart_log("RunTimeStats sent");
    }
    else if (Anx_Uart_Strcmp(buf, "taskState"))
    {
        vTaskList(uart_tx_buffer);
        Anx_UART_SendData(&huart1, "%s\r\n", uart_tx_buffer);
        Uart_log("TaskState sent");
    }
    else
    {
        Anx_UART_SendData(&huart1, "Unknown command\r\n");
        Uart_log("Unknown command");
    }



    // Uart_log("Processing completed");
}



#if (SUPPORT_RTOS == 1)

/**
 * @brief 串口接收不定长功能初始化
 *
 * @note 开启DMA接受及空闲中断
 *
 * @param huart: 串口实例
 * @param buf: DMA接收存储
 * @param buf_len: 存储器长度
 *
 */
void Anx_Uart_Init(UART_HandleTypeDef* huart)
{
    Uart_log("init start");


    // HAL_UART_Receive_IT(huart, (uint8_t*)uart_rx_buffer, USART_RX_BUFFER_MAX);
    // //__HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);
    __HAL_UART_ENABLE_IT(huart, UART_IT_IDLE);
    HAL_UART_Receive_DMA(huart, (uint8_t*)uart_rx_buffer, USART_RX_BUFFER_MAX);
    // HAL_UART_Receive_IT(huart, (uint8_t*)uart_rx_buffer, USART_RX_BUFFER_MAX);

    uart_rx_mail = osMailCreate(osMailQ(uart_rx_mail), NULL);

    osThreadDef(uart_rx_task, Anx_UartRx_Task, osPriorityNormal, 0, 256);//广播任务
    uart_rx_handle = osThreadCreate(osThread(uart_rx_task), &uart_rx_mail);
    //osThreadCreate(osThread(uart_rx_task), &uart_rx_mail);

    Anx_UART_SendData(&huart1, "UART Init\r\n");
    Uart_log("init completed");
}


/**
 * @brief 串口接收数据处理函数
 *
 * @note 对接收到的数据进行处理
 *
 * @param argument: 邮箱id
 *
 */
void Anx_UartRx_Task(void const* argument)
{
    osMailQId* mail = (osMailQId*)argument;
    osEvent evt;
    char* str;

    Uart_log("rx task start");
    while (1)
    {
        // vTaskDelay(pdMS_TO_TICKS(100));
        evt = osMailGet(*mail, osWaitForever);        // wait for mail
        if (evt.status == osEventMail)
        {
            // Uart_log("get mail");
            /**********   处理接收到的邮件   **********/
            str = evt.value.p;
            if (str == NULL)
                continue;

            Anx_Rx_Process(str, uart_rx_index);

            /**********   处理接收到的邮件   **********/
            // memset(str, 0, USART_RX_BUFFER_MAX);    // 清空邮件内容
        }
    }
}

/**
 * @brief 串口回调函数
 *
 * @note 该函数需要完成调用，stm32f4xx_it.c
 *       接收数据完成后，用于通知其他任务进行处理
 *
 * @param huart: 串口实例
 *
 */
void Anx_UART_Rx_Callback(UART_HandleTypeDef* huart)
{
    if ((__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE) != RESET))	    // 获得串口空闲中断标志
    {
        __HAL_UART_CLEAR_IDLEFLAG(huart);	// 清除空闲中断标志
        HAL_UART_DMAStop(huart);	                        // 停止DMA传输，防止数据覆盖

        uart_rx_index = USART_RX_BUFFER_MAX - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);     // 计算实际接收的数据长度

        /********************* 添加缓存失效操作 *********************/
        // 如果你的 MCU 有 D-Cache，请取消下面这行代码的注释
        SCB_InvalidateDCache_by_Addr((uint32_t*)uart_rx_buffer, uart_rx_index);

        if (uart_rx_index > 0)
        {
            uart_rx_buffer[uart_rx_index] = '\0';                              // 在接收数据的末尾添加字符串结束符（适用于ASCII数据）
            osMailPut(uart_rx_mail, uart_rx_buffer);
        }

        // memset(uart_rx_buffer,0,sizeof(uart_rx_buffer));                 // 清空接收缓冲区
        HAL_StatusTypeDef status = HAL_UART_Receive_DMA(huart, (uint8_t*)uart_rx_buffer, USART_RX_BUFFER_MAX);       // 重新开启DMA，准备接收下一帧数据。
        if(status != HAL_OK)
        {
            Uart_log("HAL_UART_Receive_DMA error: %d", status);
        }
    }
}

void HAL_UART_ErrorCallback(UART_HandleTypeDef* huart)
{
    if (huart->Instance == USART1)
    {
        Uart_log("UART error, code: 0x%lX", huart->ErrorCode);
    }
}



/**
 * @brief 串口发送函数
 *
 * @note 允许使用可变参数
 *
 * @param huart: 串口实例
 * @param data: 发送的字符串
 *
 */
void Anx_UART_SendData(UART_HandleTypeDef* huart, char* data, ...)
{
    int len;

    va_list ap;
    va_start(ap, data);
    vsprintf(uart_tx_buffer, data, ap);
    va_end(ap);

    len = strlen(uart_tx_buffer);

    // taskENTER_CRITICAL();
    HAL_UART_Transmit(huart, (uint8_t*)uart_tx_buffer, len, 20);
    // taskEXIT_CRITICAL();
}
#else

/**
 * @brief 串口接收数据处理函数
 *
 * @note 对接收到的数据进行处理
 *
 * @param argument: 邮箱id
 *
 */
void Anx_UartRx_Task(void const* argument)
{
    if (uart_rx_flag == 0)
        return;

    uart_rx_flag = 0;
    Uart_log("len:%d\r\n", uart_rx_index);
    Uart_log("%s\r\n", uart_rx_buffer);


    Anx_Rx_Process(uart_rx_buffer, uart_rx_index);

    /**********   处理接收到的邮件   **********/
    Uart_log("Processing completed\r\n");
    memset(uart_rx_buffer, 0, USART_RX_BUFFER_MAX);    // 清空邮件内容
}

/**
 * @brief 串口回调函数
 *
 * @note 该函数需要完成调用，stm32f4xx_it.c
 *       接收数据完成后，用于通知其他任务进行处理
 *
 * @param huart: 串口实例
 *
 */
void Anx_UART_Rx_Callback(UART_HandleTypeDef* huart)
{
    if ((__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE) != RESET))	    // 获得串口空闲中断标志
    {
        __HAL_UART_CLEAR_IDLEFLAG(huart);	// 清除空闲中断标志
        HAL_UART_DMAStop(huart);	                        // 停止DMA传输，防止数据覆盖

        uart_rx_index = USART_RX_BUFFER_MAX - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);     // 计算实际接收的数据长度


        if (uart_rx_index > 0)
        {
            uart_rx_buffer[uart_rx_index] = '\0';                              // 在接收数据的末尾添加字符串结束符（适用于ASCII数据）
            uart_rx_flag = 1;
        }

        // memset(uart_rx_buffer,0,sizeof(uart_rx_buffer));                 // 清空接收缓冲区
        HAL_UART_Receive_DMA(huart, (uint8_t*)uart_rx_buffer, USART_RX_BUFFER_MAX);       // 重新开启DMA，准备接收下一帧数据。
    }
}

void HAL_UART_ErrorCallback(UART_HandleTypeDef* huart)
{
    if (huart->Instance == USART1)
    {
        // Debug_isr("UART error\r\n");
    }
}


/**
 * @brief 串口接收不定长功能初始化
 *
 * @note 开启DMA接受及空闲中断
 *
 * @param huart: 串口实例
 * @param buf: DMA接收存储
 * @param buf_len: 存储器长度
 *
 */
void Anx_Uart_Init(UART_HandleTypeDef* huart)
{
    Uart_log("init start\r\n");


    // HAL_UART_Receive_IT(huart, (uint8_t*)uart_rx_buffer, USART_RX_BUFFER_MAX);
    // //__HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);
    __HAL_UART_ENABLE_IT(huart, UART_IT_IDLE);
    HAL_UART_Receive_DMA(huart, (uint8_t*)uart_rx_buffer, USART_RX_BUFFER_MAX);
    // HAL_UART_Receive_IT(huart, (uint8_t*)uart_rx_buffer, USART_RX_BUFFER_MAX);

    memset(uart_rx_buffer, 0, USART_RX_BUFFER_MAX);
    //osThreadCreate(osThread(uart_rx_task), &uart_rx_mail);

    Uart_log("init completed\r\n");
}



/**
 * @brief 串口发送函数
 *
 * @note 允许使用可变参数
 *
 * @param huart: 串口实例
 * @param data: 发送的字符串
 *
 */
void Anx_UART_SendData(UART_HandleTypeDef* huart, char* data, ...)
{
    int len;

    va_list ap;
    va_start(ap, data);
    vsprintf(uart_tx_buffer, data, ap);
    va_end(ap);

    len = strlen(uart_tx_buffer);

    HAL_UART_Transmit(huart, (uint8_t*)uart_tx_buffer, len, 20);
}


#endif

/**
 * @brief 串口数据比较函数
 *
 * @note 用于比较接收到的字符串命令
 *
 * @param buf: 目标命令
 * @param desc: 接收数据
 *
 */
char Anx_Uart_Strcmp(char* buf, char* desc)
{
    if (strcmp(buf, desc) == 0)
        return true;
    return false;
}